#include <QHBoxLayout>
#include <QString>
#include <gsl/gsl_randist.h>
#include "hotspot.h"
#include "simulator.h"

Hotspot hotspot[MAXHOTSPOT];
extern MapBlock* mapblock[SIZE][SIZE];

extern const gsl_rng_type * T;
extern gsl_rng *r;

// Set hot spot property
void
Hotspot::Set(int xcenter,int ycenter,
		          double sigmax, double sigmay, int users)
{
	this->xcenter = xcenter;this->ycenter = ycenter;
	this->sigmax = sigmax;this->sigmay = sigmay;
	this->users = users;
}

// GUI input hot spot
void
Simulator::SetHotspot()
{
	for(int i = 0; i < HotSpots->value(); i++)
	{
		bool ok1,ok2,ok3;
		double tmp1 = hotspot_config[i]->Sigmax->text().toDouble(&ok1),
			   tmp2 = hotspot_config[i]->Sigmay->text().toDouble(&ok2);
		int	   tmp3 = hotspot_config[i]->Users->text().toInt(&ok3);

		if ( hotspot_config[i]->xcenter >=0 && hotspot_config[i]->ycenter >= 0
			 && ok1 && ok2 && ok3)
		{
			hotspot[i].Set(hotspot_config[i]->xcenter, hotspot_config[i]->ycenter,
				           tmp1,tmp2,
				           tmp3);
			citymap->numHotspot = i+1;
		}
	}
	citymap->GenerateTraffic();
}

// Generate users of each block
void
CityMap::GenerateTraffic()
{
	for (int i = 0; i < SIZE; i++)
	{
		for(int j = 0; j < SIZE; j++)
		{
			mapblock[i][j]->userNumber = 0;
		}
	}
	for(int i = 0; i< SIZE*SIZE * COMMONDENSITY; i++)
	{
		mapblock[int(gsl_rng_uniform (r)*SIZE)][int(gsl_rng_uniform (r)*SIZE)]->userNumber += 1;
	}

	for(int i = 0; i < numHotspot; i++)
	{
		for(int j = 0; j < hotspot[i].users; j++)
		{
			double tempx=gsl_ran_gaussian_ziggurat (r, hotspot[i].sigmax),
				   tempy=gsl_ran_gaussian_ziggurat (r, hotspot[i].sigmay);
			int xt = int(hotspot[i].xcenter + tempx),
				yt = int(hotspot[i].ycenter + tempy);
			if ( xt < SIZE && xt >= 0 && yt < SIZE && yt >= 0 )
			{
				mapblock[xt][yt]->userNumber += 1;
			}
		}
	}
	for (int i = 0; i < SIZE; i++)
	{
		for(int j = 0; j < SIZE; j++)
		{
			mapblock[i][j]->CalculateTraffic();
		}
	}
	RepaintAll();
}

// Calculate traffic by user number
void
MapBlock::CalculateTraffic()
{
	if( userNumber == 0 )
	{
		totalDayTraffic = 0;
		totalNightTraffic = 0;
		return;
	}
	double daytraffic = 0 , nighttraffic = 0;
	for( int i = 0 ; i < userNumber ; i++ )
	{
		// Erlang Theory should be applied here!!!!
		daytraffic += 12200 * 1.5 /40.0;
		nighttraffic += 6100 * 1.5 /40.0;
	}
	totalDayTraffic = daytraffic;
	totalNightTraffic = nighttraffic;
}

int Hotspot_Config::select = -1;

// GUI of hot spot configuration
Hotspot_Config::Hotspot_Config(int i)
: num(i)
{
	xcenter = hotspot[i].xcenter; ycenter = hotspot[i].ycenter;
	if (xcenter >=0 && ycenter >=0)
	{
		Center = new QPushButton(QString::number(xcenter)+','+QString::number(ycenter));
		Sigmax = new QLineEdit(QString::number(hotspot[i].sigmax));
		Sigmay = new QLineEdit(QString::number(hotspot[i].sigmax));
		Users  = new QLineEdit(QString::number(hotspot[i].users));
	}
	else
	{
		Center = new QPushButton(tr("Center"));
		Sigmax = new QLineEdit("8.5"); Sigmay = new QLineEdit("8.5");
		Users  = new QLineEdit("30000");
		this->hide();
	}
	Center->setMaximumWidth(50);
	Center->setCheckable(true);
	connect(Center,SIGNAL(toggled(bool)),this,SLOT(SelectCenter(bool)));

	sigmaxlabel = new QLabel(QChar(0x03C3)+QString("<sub>x</sub>"));
	sigmaylabel = new QLabel(QChar(0x03C3)+QString("<sub>y</sub>"));
	userslabel = new QLabel(tr("N"));
	Sigmax->setMaximumWidth(35);
	Sigmay->setMaximumWidth(35);
	Users->setMaximumWidth(55);

	QHBoxLayout *layout  = new QHBoxLayout();

	layout->addWidget(Center);
	layout->addWidget(sigmaxlabel);
	layout->addWidget(Sigmax);
	layout->addWidget(sigmaylabel);
	layout->addWidget(Sigmay);
	layout->addWidget(userslabel);
	layout->addWidget(Users);

	this->setLayout(layout);
	this->setTitle("Hot Spot "+QString::number(i));

}

// Set center in the map
void
Hotspot_Config::SetCenter(int x, int y)
{
	if (num == select)
	{
		Center->setChecked(false);
		select = -1;
		xcenter = x; ycenter = y;
		Center->setText(QString::number(x)+','+QString::number(y));
	}
}

// Select center in the map
void
Hotspot_Config::SelectCenter(bool checked)
{
	if (checked)
	{
		select = num;
		Center->setText("In Map");
	}
	else
	{
		select = -1;
		if (xcenter >=0 && ycenter >=0)
		{
			Center->setText(QString::number(xcenter)+','+QString::number(ycenter));
		}
		else
		{
			Center->setText("Center");
		}
	}
}

void
Simulator::InputHotSpots(int num)
{
	for(int i = 0; i < num; i++)
	{
		hotspot_config[i]->show();
	}
	for(int i = num; i< MAXHOTSPOT; i++)
	{
		hotspot_config[i]->hide();
	}
	if( num > 0 )
	{
		SetHotNumber->setEnabled( true );
	}
	else
	{
		SetHotNumber->setEnabled( false );
	}
}
